package com.computer.fundamentals.algorithm.simulate;

/**
 * 提取字符串的数字部分，并转换为整数，本题可以采用两种方法
 *  1. 有限状态机
 *  2. if...else...逻辑处理
 */
public class Atoi {

    /**
     * 算法步骤：
     * 1. 读入字符串并丢弃无用的前导空格
     * 2. 检查下一个字符（假设还未到字符末尾）为正还是负号，读取该字符（如果有）。
     *    确定最终结果是负数还是正数。 如果两者都不存在，则假定结果为正。
     * 3. 读入下一个字符，直到到达下一个非数字字符或到达输入的结尾。
     *    字符串的其余部分将被忽略。
     * 4. 将前面步骤读入的这些数字转换为整数（即，"123" -> 123， "0032" -> 32）。
     *    如果没有读入数字，则整数为 0 。必要时更改符号（从步骤 2 开始）。
     * 5. 如果整数数超过 32 位有符号整数范围 [−2^31, 2^31− 1] ，
     *    需要截断这个整数，使其保持在这个范围内。
     *    具体来说，小于 −2^31 的整数应该被固定为 −2^31 ，
     *    大于 2^31− 1 的整数应该被固定为 2^31− 1 。
     * 返回整数作为最终结果。
     */
    public int myAtoi(String s) {
        int plusAndMinusCount = 0; // 正号和负号的数量，最多为1
        boolean minus = false;
        // 删除前缀空格、标记正负、排除首个非空、非正负号字符为字母的情况
        for (int i = 0;i < s.length();i++) {
            char ch = s.charAt(i);
            if (ch <= '9' && ch >= '0') {
                s = s.substring(i, s.length());
                break;
            }
            if (ch == '+' || ch == '-') {
                if (++plusAndMinusCount > 1) {
                    s = "";
                    break;
                }
                if (ch == '-') {
                    minus = true;
                }
            }
            if (ch >= 'A' && ch <= 'z' || ch == '.' || (plusAndMinusCount == 1 && ch == ' ')) {
                s = "";
                break;
            }
        }

        // 遍历得到s的数字部分
        for (int j = 0;j < s.length();j++) {
            if (!(s.charAt(j) <= '9' && s.charAt(j) >= '0')) {
                s = s.substring(0, j);
                break;
            }
        }

        // 删除前导0
        for (int k = 0;k < s.length();k++) {
            if (s.charAt(k) != '0') {
                s = s.substring(k, s.length());
                break;
            }
        }

        // 如果s为空，直接返回0
        if (s.equals("")) {
            return 0;
        }

        // 转换
        long res = 0;
        for (int l = 0;l < s.length();l++) {
            res = res * 10 + Integer.parseInt(s.charAt(l) + "");
            if (minus && res > Integer.MAX_VALUE) {
                return Integer.MIN_VALUE;
            }
            if (!minus && res >= Integer.MAX_VALUE) {
                return Integer.MAX_VALUE;
            }
        }

        return minus ? (int) (res * (-1)) : (int) res;
    }

    /**
     * 详细测试前往 https://leetcode-cn.com/problems/string-to-integer-atoi/
     */
    public static void main(String[] args) {

        Atoi atoi = new Atoi();

        System.out.println("------------测试------------");
        System.out.println(atoi.myAtoi("  + 431"));
        System.out.println(atoi.myAtoi("wk 1234"));
        System.out.println(atoi.myAtoi("-1111111111111111111"));

    }
}